{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Build Hotnet2 Network Container\n",
    "In this notebook, I want to construct the network container for the Hotnet2 data. In order to do that, I have to do the following:\n",
    "1. Construct a network from heat scores and edgelist (data in Hotnet2 github repo) or from network and mutation frequencies directly from TCGA.\n",
    "2. Get labels (positive and negative) from OMIM\n",
    "3. Do train/test split and save the whole thing\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/home/sasse/.local/lib/python3.6/site-packages/h5py/__init__.py:34: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.\n",
      "  from ._conv import register_converters as _register_converters\n",
      "/home/sasse/.local/lib/python3.6/site-packages/matplotlib/__init__.py:886: MatplotlibDeprecationWarning: \n",
      "examples.directory is deprecated; in the future, examples will be found relative to the 'datapath' directory.\n",
      "  \"found relative to the 'datapath' directory.\".format(key))\n"
     ]
    }
   ],
   "source": [
    "import pandas as pd\n",
    "import numpy as np\n",
    "import h5py\n",
    "import networkx as nx\n",
    "import matplotlib.pyplot as plt\n",
    "import seaborn\n",
    "from sklearn.model_selection import train_test_split\n",
    "\n",
    "import mygene\n",
    "from goatools.base import download_go_basic_obo, download_ncbi_associations\n",
    "from goatools.associations import read_ncbi_gene2go\n",
    "from goatools.go_search import GoSearch\n",
    "\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "VAL_SIZE = 0\n",
    "TEST_RATIO = 0.4\n",
    "BALANCE = False\n",
    "USE_HEAT_SCORES = False\n",
    "NETWORK_TO_USE = 'cpdb' # can be either CPDB or iref"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_gene_symbols(list_of_ensembl_ids):\n",
    "    # get Ensembl IDs for gene names\n",
    "    mg = mygene.MyGeneInfo()\n",
    "    res = mg.querymany(list_of_ensembl_ids,\n",
    "                       scopes='ensembl.gene',\n",
    "                       fields='symbol',\n",
    "                       species='human', returnall=True\n",
    "                      )\n",
    "\n",
    "    def get_symbol_and_ensembl(d):\n",
    "        if 'symbol' in d:\n",
    "            return [d['query'], d['symbol']]\n",
    "        else:\n",
    "            return [d['query'], None]\n",
    "\n",
    "    node_names = [get_symbol_and_ensembl(d) for d in res['out']]\n",
    "    # now, retrieve the names and IDs from a dictionary and put in DF\n",
    "    #print (\"{} gene names (symbols) mapped successfully\".format(len(ens_ids)))\n",
    "    node_names = pd.DataFrame(node_names, columns=['Ensembl_ID', 'Symbol']).set_index('Ensembl_ID')\n",
    "    node_names.dropna(axis=0, inplace=True)\n",
    "    return node_names"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. Construct Network"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "querying 1-1000...done.\n",
      "querying 1001-2000...done.\n",
      "querying 2001-3000...done.\n",
      "querying 3001-4000...done.\n",
      "querying 4001-5000...done.\n",
      "querying 5001-6000...done.\n",
      "querying 6001-7000...done.\n",
      "querying 7001-8000...done.\n",
      "querying 8001-9000...done.\n",
      "querying 9001-10000...done.\n",
      "querying 10001-11000...done.\n",
      "querying 11001-12000...done.\n",
      "querying 12001-13000...done.\n",
      "querying 13001-14000...done.\n",
      "querying 14001-14212...done.\n",
      "Finished.\n",
      "3 input query terms found no hit:\n",
      "\t['ENSG00000116957', 'ENSG00000133808', 'ENSG00000284413']\n"
     ]
    }
   ],
   "source": [
    "# read edgelist and names\n",
    "if NETWORK_TO_USE.lower() == 'iref':\n",
    "    net_file = '../data/pancancer/hotnet2/networks/irefindex9/irefindex9_edge_list'\n",
    "    name_file = '../data/pancancer/hotnet2/networks/irefindex9/irefindex9_index_gene'\n",
    "    edgelist = pd.read_csv(net_file, sep=' ', header=None,\n",
    "                           names=['from', 'to', 'weight'])\n",
    "    index = pd.read_csv(name_file, sep=' ', header=None, names=['name'])\n",
    "\n",
    "    # build network and relabel nodes to match with real names\n",
    "    G = nx.from_pandas_dataframe(edgelist, source='from', target='to', edge_attr=None)\n",
    "    print (\"Edges: {}\\tNodes: {}\".format(G.number_of_edges(), G.number_of_nodes()))\n",
    "    _ = nx.relabel_nodes(G, index.to_dict()['name'], copy=False)\n",
    "elif NETWORK_TO_USE == 'cpdb':\n",
    "    # load CPDB network from file\n",
    "    edgelist = pd.read_csv('../../data/networks/CPDB_ensg_edgelist.tsv', sep='\\t')\n",
    "    # construct networkx graph\n",
    "    G = nx.from_pandas_edgelist(df=edgelist, source='partner1', target='partner2', edge_attr='confidence')\n",
    "    node_list = list(G.nodes())\n",
    "    node_names = get_gene_symbols(node_list)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(0.5, 1.0, 'Node Degree Distribution of Genes in PPI')"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\nMJIkSZI0eAYjSZIkSYNnMJIkSZI0eAYjSZIkSYNnMJIkSZI0eAYjSZIkSYPXazBK8vwk30zyjSQf\nSnLnJHsmOTvJmiQfTrJVO/dObX9NO76sz9okSZIkaUpvwSjJUuC5wPKq+h1gC+DJwBuAt1TVvYBr\ngSPaJUcA17b2t7TzJEmSJKl3fQ+l2xLYOsmWwDbAFcABwKnt+Erg0LZ9SNunHT8wSXquT5IkSZL6\nC0ZVdTnwD8D3GQWi64FzgOuq6tZ22mXA0ra9FLi0XXtrO3+nvuqTJEmSpCl9DqXbgVEv0J7A3YFt\ngUdthPsemWR1ktVr167d0NtJkiRJUq9D6R4B/HdVra2qW4CPAvsD27ehdQC7AZe37cuB3QHa8bsC\n16x706o6oaqWV9XyJUuW9Fi+JEmSpKHoMxh9H9gvyTZtrtCBwLeAzwNPaOccBpzWtle1fdrxz1VV\n9VifJEmSJAH9zjE6m9EiCucCF7THOgF4CfCCJGsYzSE6sV1yIrBTa38BsKKv2iRJkiRpXDblTpnl\ny5fX6tWrF7oMSZIkSYtUknOqavlc52051wnqbtmK02c8dvGxB0+wEkmSJEnz0ff3GEmSJEnSomcw\nkiRJkjR4BiNJkiRJg2cwkiRJkjR4BiNJkiRJg2cwkiRJkjR4BiNJkiRJg2cwkiRJkjR4BiNJkiRJ\ng2cwkiRJkjR4BiNJkiRJg2cwkiRJkjR4BiNJkiRJg2cwkiRJkjR4BiNJkiRJg2cwkiRJkjR4BiNJ\nkiRJg2cwkiRJkjR4BiNJkiRJg2cwkiRJkjR4BiNJkiRJg2cwkiRJkjR4BiNJkiRJg2cwkiRJkjR4\nBiNJkiRJg2cwkiRJkjR4BiNJkiRJg2cwkiRJkjR4BiNJkiRJg2cwkiRJkjR4BiNJkiRJg2cwkiRJ\nkjR4BiNJkiRJg2cwkiRJkjR4BiNJkiRJg2cwkiRJkjR4BiNJkiRJg2cwkiRJkjR4BiNJkiRJg2cw\nkiRJkjR4BiNJkiRJg2cwkiRJkjR4BiNJkiRJg9dbMEpy7yRfH/u5IcnzkuyY5DNJLmy/d2jnJ8lx\nSdYkOT/Jvn3VJkmSJEnjegtGVfXdqtqnqvYBfg/4CfAxYAVwZlXtBZzZ9gEOAvZqP0cCx/dVmyRJ\nkiSNm9RQugOB71XVJcAhwMrWvhI4tG0fApxUI18Btk+y64TqkyRJkjRgkwpGTwY+1LZ3qaor2vaV\n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\ngg==\n",
      "text/plain": [
       "<Figure size 1008x576 with 1 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# plot node degree to check if distribution follows power law\n",
    "node_degrees = np.array([i[1] for i in list(G.degree())])\n",
    "fig = plt.figure(figsize=(14, 8))\n",
    "bins = np.linspace(1, 100, 100)\n",
    "ax = plt.hist(node_degrees, bins)\n",
    "plt.xlabel('Node Degree')\n",
    "plt.ylabel('Number of genes with node degree')\n",
    "plt.title('Node Degree Distribution of Genes in PPI')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# self interactions?\n",
    "assert (np.diag(nx.to_numpy_array(G)).sum() == 0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. Get Features\n",
    "Have a look at the HotNet2 heat scores and gene expression data for the cancer types."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 55,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "# genes with heat scores: 11565\n"
     ]
    }
   ],
   "source": [
    "# get edgelist with names from the networkx graph\n",
    "l = nx.to_edgelist(G)\n",
    "f = [i[0] for i in l]\n",
    "t = [i[1] for i in l]\n",
    "edges_names = pd.DataFrame(np.array([f, t]).T, columns=['from_node', 'to_node'])\n",
    "node_list = pd.DataFrame(list(set().union(f, t)), columns=['name'])\n",
    "\n",
    "# get features and see which ones are in the network\n",
    "\n",
    "# get heat scores and see which ones are in our network\n",
    "heat_file = '../../data/pancancer/hotnet2/heats/pan12.gene2freq.txt'\n",
    "heat_scores = pd.read_csv(heat_file, header=None, sep=' ',\n",
    "                          names=['gene_name', 'heat'], index_col=0)\n",
    "nx.set_node_attributes(G, 0, name='heat')\n",
    "nx.set_node_attributes(G, heat_scores.to_dict()['heat'], name='heat')\n",
    "print (\"# genes with heat scores: {}\".format(len(heat_scores)))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 56,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "# genes with gene expression: 8934\n"
     ]
    }
   ],
   "source": [
    "features = pd.read_csv('../../data/pancancer/TCGA/expression/pancan12_rsem_matrix_tumor_type_means.tsv', sep='\\t')\n",
    "features.set_index('#Gene', inplace=True)\n",
    "genes_with_features = features[features.index.isin(node_names.Symbol)]\n",
    "print (\"# genes with gene expression: {}\".format(genes_with_features.shape[0]))\n",
    "default_val = np.zeros(12) # 12 different cancers\n",
    "nx.set_node_attributes(G, default_val, 'features')\n",
    "nx.set_node_attributes(G, genes_with_features.T.to_dict('list'), 'features')\n",
    "assert (len(nx.get_node_attributes(G, 'features')) == len(G.nodes()))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3. Get Labels\n",
    "The positives can come from the list of Vogelstein et al. while the negatives can be those genes not present in OMIM, not in the list of Vogelstein and with a low score in COSMIC."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 58,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Got 125 cancer genes\n",
      "Got 54 oncogenes and 66 tumour suppressors\n"
     ]
    }
   ],
   "source": [
    "cancer_gene_list = pd.read_csv('../../data/pancancer/vogelstein/table_s2a.csv', sep='\\t', header=0)\n",
    "print (\"Got {} cancer genes\".format(cancer_gene_list.shape[0]))\n",
    "cancer_gene_list.columns = [i.strip('*') for i in cancer_gene_list.columns]\n",
    "cancer_genes = cancer_gene_list[cancer_gene_list['Gene Symbol'].isin(node_names.Symbol)]\n",
    "oncogenes = cancer_genes[cancer_genes.Classification == \"Oncogene\"]\n",
    "suppressors = cancer_genes[cancer_genes.Classification == \"TSG\"]\n",
    "print (\"Got {} oncogenes and {} tumour suppressors\".format(oncogenes.shape[0], suppressors.shape[0]))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#cancer_gene_list.head(10)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 64,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "14082 genes are in network but not in Vogelstein list (oncogenes)\n",
      "2582 genes are in network but not in oncogenes and not in OMIM\n",
      "2531 genes in network but not in oncogenes, OMIM and COSMIC cancer gene census.\n"
     ]
    }
   ],
   "source": [
    "# get rid of the vogelstein cancer genes\n",
    "not_positives = node_names[~node_names.Symbol.isin(cancer_gene_list['Gene Symbol'])]\n",
    "print (\"{} genes are in network but not in Vogelstein list (oncogenes)\".format(not_positives.shape[0]))\n",
    "\n",
    "# get rid of the OMIM disease genes\n",
    "omim_genes = pd.read_csv('../../data/pancancer/OMIM/genemap2.txt', sep='\\t', comment='#', header=None)\n",
    "omim_genes.columns = ['Chromosome', 'Genomic Position Start', 'Genomic Position End', 'Cyto Location',\n",
    "                      'Computed Cyto Location', 'Mim Number', 'Gene Symbol', 'Gene Name',\n",
    "                      'Approved Symbol', 'Entrez Gene ID', 'Ensembl Gene ID', 'Comments',\n",
    "                      'Phenotypes', 'Mouse Gene Symbol/ID']\n",
    "omim_gene_names = []\n",
    "for idx, row in omim_genes.iterrows():\n",
    "    gene_names = row['Gene Symbol'].strip().split(',')\n",
    "    omim_gene_names += gene_names\n",
    "omim_gene_names = list(set(omim_gene_names))\n",
    "not_omim_not_pos = not_positives[~not_positives.Symbol.isin(omim_gene_names)]\n",
    "print (\"{} genes are in network but not in oncogenes and not in OMIM\".format(not_omim_not_pos.shape[0]))\n",
    "\n",
    "# get rid of genes that are not in COSMIC\n",
    "cosmic_gene_scores = pd.read_csv('../../data/pancancer/cosmic/cancer_gene_census.csv', header=0)\n",
    "negatives = not_omim_not_pos[~not_omim_not_pos.Symbol.isin(cosmic_gene_scores['Gene Symbol'])]\n",
    "print (\"{} genes in network but not in oncogenes, OMIM and COSMIC cancer gene census.\".format(negatives.shape[0]))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 4. Train / Test Split"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "def build_mask(nodes_with_labels, X):\n",
    "    mask = np.array(nodes_with_labels.name.isin(X.name), dtype=np.uint8)\n",
    "    # verify that all nodes from mask are in X and vice versa\n",
    "    t = nodes_with_labels[mask.astype(bool)] # df for the mask\n",
    "    assert (np.all(t.name.isin(X.name)) and np.all(X.name.isin(t.name)))\n",
    "    return mask\n",
    "\n",
    "def build_y(nodes_with_labels, X):\n",
    "    y_t = np.array([node_list.name.isin(X.name) & node_list.cancer_gene], dtype=np.uint8).T\n",
    "    return y_t\n",
    "\n",
    "def balanced_stratified_split(X, test_ratio):\n",
    "    # calculate number of labels for both sets\n",
    "    num_labels_total = X.label.sum()\n",
    "    num_labels_train = int(num_labels_total * (1-test_ratio))\n",
    "    num_labels_test = num_labels_total - num_labels_train\n",
    "    num_positives = X.cancer_gene.sum()\n",
    "    num_pos_train = int(num_positives*(1-test_ratio))\n",
    "    num_pos_test = num_positives - num_pos_train\n",
    "    # select random training set (size 2*num_labels_train)\n",
    "    X_train = X[X.cancer_gene].sample(n=num_pos_train)\n",
    "    X_train = X_train.append(X[X.non_cancer_gene].sample(n=num_pos_train))\n",
    "    # rest is test\n",
    "    X_test = X[X.label & ~X.index.isin(X_train.index)]\n",
    "    return X_train, X_test"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Split Training and Testing with 40.0% test nodes\n",
      "Training Nodes: 1428\t#Positive Genes in Train Set: 74\n",
      "Testing Nodes: 952\t#Positive Genes in Test Set: 49\n"
     ]
    }
   ],
   "source": [
    "# add columns for positives and negatives\n",
    "node_list = pd.DataFrame(nx.to_pandas_adjacency(G).index, columns=['name'])\n",
    "node_list['cancer_gene'] = node_list.name.isin(cancer_gene_list['Gene Symbol'])\n",
    "node_list['non_cancer_gene'] = node_list.name.isin(negatives.name)\n",
    "# add column for label in general\n",
    "node_list['label'] = node_list.cancer_gene | node_list.non_cancer_gene\n",
    "# assert that labels are set correctly\n",
    "assert (node_list[node_list.cancer_gene | node_list.non_cancer_gene].equals(node_list[node_list.label]))\n",
    "\n",
    "# split for training, testing & validation\n",
    "if BALANCE:\n",
    "    X_train, X_test = balanced_stratified_split(node_list, TEST_RATIO)\n",
    "else:\n",
    "    X_train, X_test = train_test_split(node_list[node_list.label],\n",
    "                                       test_size=TEST_RATIO,\n",
    "                                       stratify=node_list[node_list.label].cancer_gene\n",
    "                                      )\n",
    "if VAL_SIZE > 0:\n",
    "    X_val = X_train[-VAL_SIZE:]\n",
    "    X_train = X_train[:-VAL_SIZE]\n",
    "else:\n",
    "    X_val = None\n",
    "print (\"Split Training and Testing with {}% test nodes\".format(TEST_RATIO*100.))\n",
    "print (\"Training Nodes: {}\\t#Positive Genes in Train Set: {}\".format(X_train.shape[0],\n",
    "                                                                 X_train.cancer_gene.sum())\n",
    "      )\n",
    "print (\"Testing Nodes: {}\\t#Positive Genes in Test Set: {}\".format(X_test.shape[0],\n",
    "                                                               X_test.cancer_gene.sum())\n",
    "      )\n",
    "\n",
    "# construct masks\n",
    "train_mask = build_mask(node_list, X_train)\n",
    "test_mask = build_mask(node_list, X_test)\n",
    "if X_val is not None:\n",
    "    val_mask = build_mask(node_list, X_val)\n",
    "\n",
    "# construct labels\n",
    "y_train = build_y(node_list, X_train)\n",
    "y_test = build_y(node_list, X_test)\n",
    "if X_val is not None:\n",
    "    y_val = build_y(node_list, X_val)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 5. Get Ensembl IDs for Gene Names"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "querying 1-1000...done.\n",
      "querying 1001-2000...done.\n",
      "querying 2001-3000...done.\n",
      "querying 3001-4000...done.\n",
      "querying 4001-5000...done.\n",
      "querying 5001-6000...done.\n",
      "querying 6001-7000...done.\n",
      "querying 7001-8000...done.\n",
      "querying 8001-9000...done.\n",
      "querying 9001-10000...done.\n",
      "querying 10001-11000...done.\n",
      "querying 11001-12000...done.\n",
      "querying 12001-12129...done.\n",
      "Finished.\n",
      "32 input query terms found dup hits:\n",
      "\t[('TIMM22', 4), ('ARMCX5-GPRASP2', 2), ('GNAZ', 2), ('DNAJB3', 2), ('C9orf163', 2), ('XKRY2', 2), ('\n",
      "638 input query terms found no hit:\n",
      "\t['DBC1', 'ANKRD57', 'SGK196', 'IL8', 'C7orf42', 'FAM40B', 'EIF2C4', 'LPPR3', 'FAM127B', 'FAM40A', 'F\n",
      "11499 gene names (symbols) mapped successfully\n"
     ]
    }
   ],
   "source": [
    "# get Ensembl IDs for gene names\n",
    "mg = mygene.MyGeneInfo()\n",
    "res = mg.querymany(node_list.name,\n",
    "                   scopes='symbol, refseq, uniprot',\n",
    "                   fields='ensembl.gene',\n",
    "                   species='human', returnall=True\n",
    "                  )\n",
    "\n",
    "# now, retrieve the names and IDs from a dictionary and put in DF\n",
    "def get_name_and_id(x):\n",
    "    ens_id = x['ensembl'][0]['gene'] if type(x['ensembl']) is list else x['ensembl']['gene']\n",
    "    name = x['query']\n",
    "    return [name, ens_id]\n",
    "\n",
    "ens_ids = [get_name_and_id(x) for x in res['out'] if 'ensembl' in x]\n",
    "node_names_ids = pd.DataFrame(ens_ids, columns=['name', 'ID'])\n",
    "node_names_ids.set_index('name', inplace=True)\n",
    "node_names_ids = node_names_ids[~node_names_ids.index.duplicated(keep='first')]\n",
    "\n",
    "# join with node list to have the correct order and derive gene names\n",
    "nodes_with_ids = node_list.join(node_names_ids, on='name')\n",
    "nodes_with_ids.loc[nodes_with_ids.ID.isnull(), 'ID'] = nodes_with_ids[nodes_with_ids.ID.isnull()].name\n",
    "gene_names = np.vstack((np.array(nodes_with_ids.ID), np.array(nodes_with_ids.name))).transpose(1, 0)\n",
    "\n",
    "print (\"{} gene names (symbols) mapped successfully\".format(len(ens_ids)))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 6. Save To hdf5"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "scrolled": false
   },
   "outputs": [],
   "source": [
    "ppi_network = nx.to_numpy_array(G)\n",
    "# test if ppi_network (A) has the same degree as the graph\n",
    "# this should test if the features have the same ordering as the network\n",
    "assert (np.all(np.equal(ppi_network.sum(axis=0), np.array([d[1] for d in list(nx.degree(G))]))))\n",
    "\n",
    "# only one dim output (not one-hot)\n",
    "#y_train = np.array([y_train[:, 0]]).T\n",
    "#y_test = np.array([y_test[:, 0]]).T\n",
    "#if X_val is not None:\n",
    "#    y_val = np.array([y_val[:, 0]]).T\n",
    "\n",
    "# build feature vector\n",
    "node_index = nx.to_pandas_adjacency(G).index\n",
    "if USE_HEAT_SCORES:\n",
    "    attributes = nx.get_node_attributes(G, 'heat')\n",
    "    features = np.array([[attributes[i] for i in node_index]]).T\n",
    "else:\n",
    "    attributes = nx.get_node_attributes(G, 'features')\n",
    "    features = np.array([attributes[i] for i in node_index])\n",
    "\n",
    "# create gene names\n",
    "string_dt = h5py.special_dtype(vlen=str)\n",
    "\n",
    "# determine file name by parameters\n",
    "b = 'balanced' if BALANCE else 'unbalanced'\n",
    "f = 'heat' if USE_HEAT_SCORES else 'vec'\n",
    "fname = '../data/pancancer/hotnet_iref_{}_input_{}.h5'.format(f, b)\n",
    "f = h5py.File(fname, 'w')\n",
    "\n",
    "# add ppi network\n",
    "f.create_dataset('network', data=ppi_network, shape=ppi_network.shape)\n",
    "\n",
    "# add features\n",
    "f.create_dataset('features', data=features, shape=features.shape)\n",
    "# add gene names (same order as features & network)\n",
    "f.create_dataset('gene_names', data=gene_names, dtype=string_dt)\n",
    "# add labels\n",
    "f.create_dataset('y_train', data=y_train, shape=y_train.shape)\n",
    "f.create_dataset('y_test', data=y_test, shape=y_test.shape)\n",
    "if X_val is not None:\n",
    "    f.create_dataset('y_val', data=y_val, shape=y_val.shape)\n",
    "\n",
    "f.create_dataset('mask_train', data=train_mask, shape=train_mask.shape)\n",
    "f.create_dataset('mask_test', data=test_mask, shape=test_mask.shape)\n",
    "if X_val is not None:\n",
    "    f.create_dataset('mask_val', data=val_mask, shape=val_mask.shape)\n",
    "f.close()\n",
    "print (\"Container written to {}\".format(fname))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 59,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "assert (np.alltrue([gene_names[i] == node_index[i] for i in range(node_index.shape[0])]))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.8"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
